package com.yan.config;

import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * TODO
 *
 * @Author: 汪焰
 * @Date: 2021/7/5 23:32
 */
@Configuration
public class RabbitConfig {

    /**
     * 声明 死信队列
     */
    @Bean
    public Queue dlxQueue() {
        return new Queue(RabbitConstants.DLX_QUEUE_NAME);
    }

    /**
     * 声明 死信队列 交换器
     */
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange(RabbitConstants.DLX_QUEUE_EXCHANGE);
    }

    /**
     * 绑定 死信队列 到 死信交换机
     */
    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(dlxQueue())
                .to(dlxExchange())
                .with(RabbitConstants.DLX_QUEUE_ROUTING_KEY);
    }


    /**
     * 声明 订单业务 队列
     */
    @Bean
    public Queue orderQueue() {
        return new Queue(RabbitConstants.ORDER_QUEUE_NAME, true, false, false, RabbitConstants.arguments);
    }

    /**
     * 声明 订单业务 交换机
     */
    @Bean
    public DirectExchange orderExchange() {
        return new DirectExchange(RabbitConstants.ORDER_QUEUE_EXCHANGE);
    }

    /**
     * 绑定 订单队列 到 订单交换机
     */
    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue())
                .to(orderExchange())
                .with(RabbitConstants.ORDER_QUEUE_ROUTING_KEY);
    }


    @Bean
    @Autowired
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

        //1.1、确认消息是否发送到交换机，确保消息未发送到交换机返回消息

        //spring.rabbitmq.publisher-confirm-type=correlated
        //设置开启 Mandatory，才能触发回调函数，无论消息推送结果怎么样都会强制调用回调函数
        rabbitTemplate.setMandatory(true);
        // 设置确认发送到交换机的回调函数
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("ConfirmCallback:     相关数据：" + correlationData);
                System.out.println("ConfirmCallback:     确认情况：" + ack);
                System.out.println("ConfirmCallback:     原因：" + cause);

            }
        });

        //1.2、确认是否到达队列。消息没有发送到指定的队列时将消息返回，而不是丢弃

        //spring.rabbitmq.publisher-returns=true
        //设置确认消息已发送到队列的回调
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                System.out.println("ReturnsCallback:  消息：" + returnedMessage.getMessage());
                System.out.println("ReturnsCallback:  回应码：" + returnedMessage.getReplyCode());
                System.out.println("ReturnsCallback:  回应信息：" + returnedMessage.getReplyText());
                System.out.println("ReturnsCallback:  交换机：" + returnedMessage.getExchange());
                System.out.println("ReturnsCallback:  路由键：" + returnedMessage.getRoutingKey());
            }
        });
        return rabbitTemplate;
    }
}
